<template>
  <div
    ref="canvasContRef"
    class="canvas-container"
    onselectstart="return false;"
    style="-moz-user-select: none"
  >
    <div v-show="imgIsLoad" ref="canvasWrapRef" class="canvas-wrap" :style="canvasStyle">
      <canvas ref="canvasRef" class="canvas" @dragover="dragover"></canvas>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, nextTick,  } from 'vue'
const props = defineProps({
  imgUrl: {
    type: String,
    require: true,
  },
  // 拖拽的元素列表
  tagsList: {
    type: Array,
    default: () => [],
  },
  imageIndex: {
    type: Number,
    default: 0,
  },
})

const imgIsLoad = ref(false)
const canvasWrapRef = ref()
const canvasContRef = ref()
const canvasRef = ref()
const canvasValue = ref({
  width: 0,
  height: 0,
  left: 0,
  top: 0,
  scale: 1,
  rotate: 0,
  cursor: 'default',
})

const canvasStyle = computed(() => {
  const { width, height, left, top, scale, rotate, cursor } = canvasValue.value
  return {
    width: `${width}px`,
    height: `${height}px`,
    left: `${left}px`,
    top: `${top}px`,
    transform: `rotate(${rotate}deg) scale(${scale})`,
    cursor: cursor,
  }
})

onMounted(() => {
  const canvas = canvasRef.value
  const ctx = canvas.getContext('2d')
  loadImg(canvas, ctx)
  changeTool('drag')
  window.addEventListener('resize', reload)
  canvasRef.value.addEventListener('mousewheel', e => {
    let z = e.deltaY > 0 ? -0.1 : 0.1
    changeTool(z > 0 ? 'enlarge' : 'narrow')
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', reload)
})

const reload = () => {
  nextTick(() => {
    const canvas = canvasContRef.value
    canvasCenter(canvas)
  })
}

// 加载图片
const loadImg = (canvas: any) => {
  const img = new Image()
  // 图片加载成功
  img.src = props.imgUrl as any

  img.onload = e => {
    imgIsLoad.value = true

    let oHeight = canvasContRef.value.offsetHeight
    let oWidth = canvasContRef.value.offsetWidth
    canvas.width = img.width
    canvasValue.value.width = img.width
    canvas.height = img.height
    canvasValue.value.height = img.height

    if (oHeight / img.height >= oWidth / img.width) {
      canvasValue.value.scale = Number((oWidth / img.width).toFixed(1))
    } else {
      canvasValue.value.scale = Number((oHeight / img.height).toFixed(1))
    }
    canvas.style.backgroundImage = `url(${img.src})`
    canvas.style.backgroundSize = '100% 100%'
    canvasCenter(canvas)
  }
  // 图片加载失败
  img.onerror = () => {
    console.error('图片加载失败！')
  }
}

// 切换工具
const changeTool = (name: any) => {
  // 清除拖拽的按下事件
  const wrapRef = canvasWrapRef.value

  wrapRef.onmousedown = null
  const canvas = canvasRef.value
  switch (name) {
    case 'drag':
      dragCanvas(canvas)
      break
    case 'rotate':
      canvasValue.value.rotate = canvasValue.value.rotate + 90
      break
    case 'enlarge':
      canvasValue.value.scale = canvasValue.value.scale + 0.2
      break
    case 'narrow':
      canvasValue.value.scale =
        canvasValue.value.scale - 0.2 < 0.2 ? 0.2 : canvasValue.value.scale - 0.2
      break
    default:
      break
  }
  dragCanvas(canvas)
}

// 拖拽画布
const dragCanvas = canvas => {
  // 清除上次监听的事件
  const wrapRef = canvasWrapRef.value

  let isDown = false

  wrapRef.onmousedown = e => {
    const container = getPosition(canvasContRef.value)
    isDown = true
    canvasValue.value.cursor = 'move'
    // 算出鼠标相对元素的位置
    const disX = e.clientX - wrapRef.offsetLeft
    const disY = e.clientY - wrapRef.offsetTop
    console.log(canvasContRef.value)
    console.log(canvas, wrapRef)

    document.onmousemove = e => {
      if (!isDown) return

      // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
      let left = e.clientX - disX
      let top = e.clientY - disY

      // 判断canvas是否在显示范围内，减4是border=2px的原因
      const width = container.width - canvas.width / 2 - 4
      const height = container.height - canvas.height / 2 - 4

      // left = Math.min(Math.max(-canvas.width / 2, left), width);
      // top = Math.min(Math.max(-canvas.height / 2, top), height);

      canvasValue.value.left = left
      canvasValue.value.top = top
    }

    document.onmouseup = () => {
      isDown = false
      document.onmousemove = null
      canvasValue.value.cursor = 'default'
    }
  }
}

// 获取dom元素在页面中的位置与大小
const getPosition = target => {
  const width = target.offsetWidth
  const height = target.offsetHeight
  let left = 0
  let top = 0
  do {
    left += target.offsetLeft || 0
    top += target.offsetTop || 0
    target = target.offsetParent
  } while (target)
  return { width, height, left, top }
}

// canvas居中显示
const canvasCenter = (canvas: any) => {
  const wrap = getPosition(canvasContRef.value)
  const left = (wrap.width - canvas.width) / 2
  const top = (wrap.height - canvas.height) / 2
  canvasValue.value.left = left
  canvasValue.value.top = top
}

const dragover = e => {
  // 取消默认动作是为了drop事件可以触发
  e.preventDefault()
  // console.log(e)
}

const restoration = () => {
  canvasValue.value.left = 0
  canvasValue.value.top = 0
  canvasValue.value.scale = 1
  canvasValue.value.rotate = 0
}

defineExpose({
  changeTool,
  restoration,
})
</script>

<style scoped lang="less">
.canvas-container {
  width: 100%;
  height: 100%;
  position: relative;
  box-sizing: border-box;
  overflow: hidden;
}

.canvas-container .canvas-wrap {
  width: 100%;
  height: 100%;
  position: relative;
  transition: transform 0.3s;
  left: 0;
  top: 0;
}
</style>
